package com.services;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import model.Cinema;
import model.Movie;
import model.Projection;
import model.Seat;
import model.SeatPK;
import model.User;

@Stateless
public class ProjectionsService {
	@PersistenceContext(unitName = "cinema-unit")
	private EntityManager em;

	/**
	 * minutes for reservation
	 */
	private final int locked = 10;

	public List<Projection> getAllProjections() {
		Query q = em.createNamedQuery("Projection.findAll");
		List<Projection> result = q.getResultList();

		return result;
	}

	/**
	 * get Projects for given Cinema
	 * 
	 * @param cinemaId
	 * @return
	 */
	public List<Projection> getAllCinemaProjections(int cinemaId) {
		Cinema cinema = em.find(Cinema.class, cinemaId);

		return cinema != null ? cinema.getProjections()
				: new ArrayList<Projection>();

	}

	public List<Projection> getAllMovieProjections(int movieId) {
		Query q = em.createNamedQuery("getProjectionsByMovieId");
		q.setParameter("id", movieId);

		return (List<Projection>) q.getResultList();
	}

	public Projection getProjectionById(int id) {

		return em.find(Projection.class, id);

	}

	public List<Seat> getSeatsByProjectionId(int id) {

		Query q = em.createNamedQuery("getSeatsByProjectionId");
		q.setParameter("id", id);

		return (List<Seat>) q.getResultList();

	}

	/**
	 * lock and unlock seat
	 * 
	 * @param id
	 * @param user
	 * @throws NullPointerException
	 */
	public void switchLockOfSeat(SeatPK id, User user)
			throws NullPointerException {
		Seat seat = em.find(Seat.class, id);

		if (seat.getLocked().before(new Date())) {

			seat.setLocked(new Date(System.currentTimeMillis() + (locked + 1)
					* 60 * 1000));

		} else {

			seat.setLocked(new Date(System.currentTimeMillis() - (locked + 1)
					* 60 * 1000));

		}

		seat.setUser(user);

		em.merge(seat);
		em.flush();
	}

	/**
	 * switch attendance of seat
	 * 
	 * @param id
	 * @throws NullPointerException
	 */
	public void switchAttendanceOfSeat(SeatPK id) throws NullPointerException {

		Seat seat = em.find(Seat.class, id);

		if (seat.isAttended()) {

			seat.setAttended(false);

		} else {

			seat.setAttended(true);

		}

		em.merge(seat);
		em.flush();

	}

	public void payForSeats(List<Seat> seatsToPayForList, User user) {
		for (Seat seat : seatsToPayForList) {
			seat.setUser(user);
			seat.setSold(true);
			em.merge(seat);
		}
		em.flush();
	}

	/**
	 * get all users who bought seats for projection
	 * 
	 * @param id
	 *            the id of the projection
	 * 
	 * @return
	 */
	public List<User> getUsersWhoBoughtSeats(int id) {

		Query q = em.createNamedQuery("usersWhoBoughtSeats");
		q.setParameter("id", id);

		return (List<User>) q.getResultList();

	}

	/**
	 * get all users who bought seats and attended projection
	 * 
	 * @param id
	 *            the id of the projection
	 * @return
	 */
	public List<User> getUsersWhoAttendedProjection(int id) {

		Query q = em.createNamedQuery("usersWhoAttendedProjection");
		q.setParameter("id", id);

		return (List<User>) q.getResultList();

	}

	/**
	 * find user by username and set the attendance according attended
	 * 
	 * @param username
	 * @param attended
	 */
	public void setAttendanceOfSeats(String username, boolean attended)
			throws ArrayIndexOutOfBoundsException {

		Query q = em.createNamedQuery("getUserByUsername");
		q.setParameter("username", username);

		User user = ((List<User>) q.getResultList()).get(0);

		for (int i = 0; i < user.getSeats().size(); i++) {

			if (user.getSeats().get(i).isSold() == true
					&& user.getSeats().get(i).isAttended() != attended) {

				user.getSeats().get(i).setAttended(attended);

				em.merge(user.getSeats().get(i));
				em.flush();

			}

		}

	}

}